/*!
 * \file Socket.h
 * \brief Defines the abstract Socket class, providing a common interface to multiple 
 *        or layered networking protocols.
 *
 * \author Matthew Klupchak
 * \author Andres J. Tack
 */
#pragma once

#ifdef WIN32
#pragma comment(lib,"ws2_32.lib")
#include <Winsock2.h>
#else
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdexcept>
#define SOCKET int
#define INVALID_SOCKET ((SOCKET)~(0))
#define SOCKET_ERROR (-1)
#endif

#include "SocketException.h"
#include <cstring>
#include <iostream>

namespace Networking
{
	/*!
	 * \class Socket
	 * \brief An abstract wrapper of a socket object, designed to be inherited for completion
	 * per some specific protocol.
	 *
	 * This class allows any protocol to be used over a socket for those functions which are
	 * common to all protocols. Its function as an interface is primary to its role in
	 * socket library initialization (for Windows, specifically).
	 */
	class Socket
	{
		public:
			/*!
			 * \brief Performs library initialization and memory-zero routines.
			 *
			 * This constructor cannot be used to comstruct a full Socket class, because it
			 * is abstract.
			 */
			Socket ( void );

			/*!
			 * \brief Closes the socket file descriptor.
			 *
			 * If the close is unsuccessful, an error is printed on std::cerr.
			 */
			virtual ~Socket ( void );

		/*!
		 * \brief Sends all the bytes in the given buffer across the socket link.
		 *
		 * This method is reentrant; it well never be the case that only some of
		 * the bytes given are sent, and others remain.
		 *
		 * \param buffer is an array of bytes to be sent across the link.
		 * \param length is the number of bytes to read in buffer.
		 */
			virtual void Send ( const char * buffer, int length ) = 0;

		/*!
		 * \brief Receives data over the socket interface, storing a maximum of length
		 * characters in buffer.
		 *
		 * The value stored in buffer will not be null-terminated, zeroed, or otherwise
		 * sentried in any way. The returned value will dictate how many bytes are valid.
		 *
		 * \param buffer will be written with the data received from the socket.
		 * \param length is the maximum length which this method will store in buffer.
		 *
		 * \return the number of bytes received and placed in buffer.
		 */
		virtual int Receive ( char * buffer, int length ) = 0;

		protected:

			struct sockaddr_in   m_socketAddress;/*< IP address. */
			SOCKET               m_socket;/*< A SOCKET handel. */
			unsigned short       m_port;/*< The port number.*/

		private:

			void InitializeLibrary ( void );
	};
}
